#include "include/usb_host.h"
#include "include/usb_kbd.h"
#include "chip/include/sl811hst.h"


#include "core/include/aks_processor.h"
#include "core/include/process.h"
#include "core/include/types.h"


const BYTE code2Ascii[] =
{		/*	0xX0  0xX1  0xX2  0xX3  0xX4  0xX5  0xX6  0xX7  0xX8  0xX9  0xXA  0xXB  0xXC  0xXD  0xXE  0xXF */
/* 0x0X */	0xFF, 0xFF, 0xFF, 0xFF, 'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l', 
/* 0x1X */	'm',  'n',  'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z',  '1',  '2',
/* 0x2X */	'3',  '4',  '5',  '6',  '7',  '8',  '9',  '0',  0x0A, 0x1B, 0x08, 0x09, ' ',  '-',  '^',  '@',
/* 0x3X */	'[',  '\\', ']',  0x3B, ':',  0xFF, ',',  '.',  '/',  0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x4X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C,
/* 0x5X */	0x1D, 0x1F, 0x1E, 0xFD, '/',  '*',  '-',  '+',  0x0D, '1',  '2',  '3',  '4',  '5',  '6',  '7',
/* 0x6X */	'8',  '9',  '0',  '.',  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x7X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x8X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, '\\', 0xFF, '\\', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x9X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xAX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xBX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xCX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xDX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xEX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xFX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

const BYTE code2Ascii_s[] =
{		/*	0xX0  0xX1  0xX2  0xX3  0xX4  0xX5  0xX6  0xX7  0xX8  0xX9  0xXA  0xXB  0xXC  0xXD  0xXE  0xXF */
/* 0x0X */	0xFF, 0xFF, 0xFF, 0xFF, 'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L', 
/* 0x1X */	'M',  'N',  'O',  'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',  '!',  '"',
/* 0x2X */	'#',  '$',  '%',  '&',  0x27, '(',  ')',  0xFF, 0x0A, 0x1B, 0x08, 0x09, ' ',  '=',  '~',  '`',
/* 0x3X */	'{',  '\\', '}',  '+',  '*',  0xFF, '<',  '>',  '?',  0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x4X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C,
/* 0x5X */	0x1D, 0x1F, 0x1E, 0xFD, '/',  '*',  '-',  '+',  0x0D, '1',  '2',  '3',  '4',  '5',  '6',  '7',
/* 0x6X */	'8',  '9',  '0',  '.',  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x7X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x8X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, '_',  0xFF, '|',  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x9X */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xAX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xBX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xCX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xDX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xEX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xFX */	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};


void USBKBD_setLED(USB_DEV *dev, BYTE led)
{
	USB_REQUEST request;

	request.bmRequestType	= bmDATA_OUT | bmTYPE_CLASS | bmRECEIVER_INTERFACE;
	request.bRequest		= 0x09;
	request.wValue			= 0x02 << 8 | 0x00;
	request.wIndex			= 0;
	request.wLength			= 1;

	USB_ControlTransport(dev->speed, dev->adr, 0, &request, &led);
}

BYTE KBD_LED = 0;
USB_DEV *kbdDev;
void USBKBD_init(USB_DEV *dev)
{
	BYTE result;

	// set configuration 0(default)
	result = USB_setConfiguration(dev->speed, dev->adr, dev->CFG[0].bCfgIndex);

	// set boot mode
	USB_REQUEST request;

	request.bmRequestType	= bmDATA_OUT | bmTYPE_CLASS | bmRECEIVER_INTERFACE;
	request.bRequest		= 0x0B;
	request.wValue			= 0;
	request.wIndex			= 0;
	request.wLength			= 0;

	result = USB_ControlTransport(dev->speed, dev->adr, 0, &request, 0);

	// set LED -> all off
	USBKBD_setLED(dev, 0);

	// save descriptor
	kbdDev = dev;

	UART_transmitString(UART_DBG, (BYTE *)"KBD Driver was Installed\r\n");

	(void)result;

	return;
}


BYTE USBKBD_readData(USB_DEV *dev, BYTE *buf)
{
	BYTE result;
	BYTE bootPacket[8] = {0,0,0,0,0,0,0,0};
	BYTE cnt=0;
	BYTE shift = 0;
	BYTE ctrl  = 0;
	BYTE alt   = 0;

	(void)alt;
	(void)ctrl;

	result = USB_IN_transaction (dev->speed, dev->adr, 1, bootPacket, 8);

	if( result & SL811_ACK )
	{
		if(bootPacket[0] != 0)
		{
			if( bootPacket[0] & 0x01 )	ctrl  = 1;
			if( bootPacket[0] & 0x02 )	shift = 1;		
			if( bootPacket[0] & 0x04 )	alt   = 1;
		}

		BYTE i;
		for(i=2 ; i< 8 ; i++)
		{	
			BYTE c = (shift) ? code2Ascii_s[bootPacket[i]] : code2Ascii[bootPacket[i]];

			if( c == 0xFE )	// caps lock
			{
				KBD_LED = KBD_LED ^ 0x02;
				USBKBD_setLED(dev, KBD_LED);
			}
			else if( c == 0xFD ) // num lock
			{
				KBD_LED = KBD_LED ^ 0x01;
				USBKBD_setLED(dev, KBD_LED);
			}
			else if( c == 0xFC ) // scroll lock
			{
				KBD_LED = KBD_LED ^ 0x04;
				USBKBD_setLED(dev, KBD_LED);
			}
			else if( c != 0xFF) 
			{
				*buf = c;
				cnt++;
				buf++;
			}
		}
	}

	return cnt;
}

/* ------------ USB Keyboard Task(cyclic task) ------------*/
void usb_kbd_tsk(void)
{
	WORD now = TIMER_systemTick();
    if((now % 10) != 0) return;

	BYTE buf[8];
	BYTE cnt;
	cnt = USBKBD_readData(kbdDev, buf);

    for(BYTE i=0; i<cnt ; ++i)
    {
        UART_transmitByte(UART_DBG, buf[i]);
    }
}


